package com.automannn.practice.mybatis.executor;

import com.automannn.practice.mybatis.entity.PersonEntity;
import com.mysql.cj.conf.ConnectionUrlParser;
import com.mysql.cj.conf.DatabaseUrlContainer;
import com.mysql.cj.conf.HostInfo;
import com.mysql.cj.jdbc.ConnectionImpl;
import org.apache.ibatis.builder.StaticSqlSource;
import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.impl.PerpetualCache;
import org.apache.ibatis.executor.CachingExecutor;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.SimpleExecutor;
import org.apache.ibatis.mapping.*;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.managed.ManagedTransaction;
import org.apache.ibatis.type.StringTypeHandler;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author chenkh
 * @time 2021/11/5 15:21
 */
public class ExecutorTest {
    public static void main(String[] args) throws SQLException {
        DatabaseUrlContainer container =ConnectionUrlParser.parseConnectionString("jdbc:mysql://localhost:3306/zhenhe?useUnicode=true;serverTimezone=CST;characterEncoding=utf-8");
        Map<String,String> properties = new HashMap();
        properties.put("useUnicode","true");
        properties.put("serverTimezone","CST");
        properties.put("characterEncoding","utf-8");
        properties.put("dbname","zhenhe");

        HostInfo hostInfo = new HostInfo(container,"localhost",3306,"root","chenkaihai",properties);
        Connection connection=new ConnectionImpl(hostInfo);

        Configuration configuration = new Configuration();
        Transaction transaction = new ManagedTransaction(connection,false);
        /*xxx: 执行器 */
        Executor executor = new SimpleExecutor(configuration,transaction);
        /*xxx: 二级缓存 */
        Executor cacheExecutor = new CachingExecutor(executor);

        //xxx:参数映射 todo

        SqlSource sqlSource = new StaticSqlSource(configuration,"select * from person");
        MappedStatement.Builder  builder= new MappedStatement.Builder(configuration,"myMethod",sqlSource, SqlCommandType.SELECT);

        //xxx: 结果集映射
        List<ResultMap> resultMaps = new ArrayList<>();
        List<ResultMapping> resultMappings = new ArrayList<>();
        StringTypeHandler stringTypeHandler=  new StringTypeHandler();
        ResultMapping pidResultMapping = new ResultMapping.Builder(configuration,"pid","pid",stringTypeHandler).build();
        ResultMapping pnameResultMapping = new ResultMapping.Builder(configuration,"pname","pname", stringTypeHandler).build();
        resultMappings.add(pidResultMapping);
        resultMappings.add(pnameResultMapping);

        ResultMap resultMap = new ResultMap.Builder(configuration,"resultMap1",PersonEntity.class,resultMappings).build();
        resultMaps.add(resultMap);
        builder.resultMaps(resultMaps);

        //xxx: 二级缓存测试,是否启用二级缓存，取决于 MappedStatement的配置
        Cache cache = new PerpetualCache("automannnCache");
        builder.cache(cache);
        builder.useCache(true);


        MappedStatement mappedStatement = builder.build();

        Object params = null;
        RowBounds rowBounds = RowBounds.DEFAULT;
        //自定义结果集处理器
        List results = new ArrayList();
        ResultHandler<PersonEntity> resultHandler = new ResultHandler<PersonEntity>() {
            @Override
            public void handleResult(ResultContext<? extends PersonEntity> resultContext) {
                results.add(resultContext.getResultObject());
            }
        };
        //xxx:使用默认的 结果处理器，会当前查询的结果，进行返回
//        List resultList= executor.query(mappedStatement,params,rowBounds,null);
//        System.out.println(resultList);

        //xxx: 使用自定义的 结果处理器时， 无法通过返回值的方式获取查询的结果信息
        //xxx: mappedStatement: sql语句（包括结果集映射信息）
        //xxx: params: 解析好后的参数对象
        //xxx: resultHandler: 结果集处理器，查询结果以何种方式返回
//        executor.query(mappedStatement,params,rowBounds,resultHandler);

        cacheExecutor.query(mappedStatement,params,rowBounds,null);
        //xxx: 二级缓存使用前，一定要调用 commit方法，二级缓存才会生效
        cacheExecutor.commit(true);
        cacheExecutor.query(mappedStatement,params,rowBounds,null);
        System.out.println(results);
    }
}
